package com.gadgets.framework.common.util;

import com.alibaba.fastjson.JSON;
import com.gadgets.framework.common.dto.CacheRedisDTO;
import com.gadgets.framework.common.dto.SynergyRedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * 功能说明：
 * 软件版权：恒生电子股份有限公司
 *
 * @author xiujunqing
 * @version V202101.00.000
 * @data 2022-05-09
 * 修改记录：  修改日期          修改人员    修改说明
 * 2022-05-09  xiujunqing   创建文件
 */
@SuppressWarnings("unchecked")
@Component
public class RedisUtil {

    @SuppressWarnings("rawtypes")
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final String SYS_CACHE = "gadgets#sysCache";

    /**
     * 设置同步锁
     * @param lock  锁信息对象
     * @return      是否成功加锁
     */
    @SuppressWarnings("ConstantConditions")
    public boolean setNxSyncLock(SynergyRedisLock lock){
        return stringRedisTemplate.opsForValue().setIfAbsent(lock.getKey(), lock.getValue(), lock.getOutTimeSecound(), TimeUnit.SECONDS);
    }

    /**
     * 设置同步锁(设置定时时间)
     * @param lock  锁信息对象
     * @return      是否成功加锁
     */
    @SuppressWarnings("ConstantConditions")
    public boolean setNxSyncLockForWaitTm(SynergyRedisLock lock, int waitSeconds){
        // 每 500ms 重试一次
        int time = waitSeconds*2;
        boolean lockResult = false;
        do {
            lockResult = stringRedisTemplate.opsForValue().setIfAbsent(lock.getKey(), lock.getValue(), lock.getOutTimeSecound(), TimeUnit.SECONDS);
            // 如果在重试时间内获取锁成功了，则返回结果，否则检查是否进行下一次重试
            if(lockResult){
                break;
            }
            time--;
        }while (time>0);
        return lockResult;
    }

    /**
     * 删除同步锁
     * @param lock  锁信息对象
     * @return      是否已删除
     */
    @SuppressWarnings("ConstantConditions")
    public boolean deleteSyncLock(SynergyRedisLock lock){
        return stringRedisTemplate.delete(lock.getKey());
    }

    /**
     * 按key向缓存中加入指定缓存信息
     * @param redisDTO  缓存对象
     */
    public void setNxStringCacheKey(CacheRedisDTO<String> redisDTO){
        stringRedisTemplate.opsForValue().set(redisDTO.getKey(), redisDTO.getValue());
    }

    /**
     * 获取指定类型，指定key的缓存数据
     * @param key       缓存key
     * @return          缓存value
     */
    public String getNxStringCacheByKey(String key){
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 将指定Key推送给Redis
     * @param key
     * @param value
     */
    public void setCacheByKey(String key, Object value){
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 将指定Key保存到Redis缓存中
     * @param key
     * @param val
     */
    public void setCacheForSysParam(String key, Object val){
        HashMap<String ,Object> sysParamMap = getCacheMapForSysParam();
        if(null==sysParamMap){
            sysParamMap = new HashMap<>();
        }
        sysParamMap.put(key, val);
        stringRedisTemplate.opsForValue().set(SYS_CACHE, JSON.toJSONString(sysParamMap));
    }

    public HashMap<String ,Object> getCacheMapForSysParam(){
        String sysCache = stringRedisTemplate.opsForValue().get(SYS_CACHE);
        if(StringUtils.isBlank(sysCache)){return null;}
        HashMap<String ,Object> sysParamMap = JSON .parseObject(sysCache, HashMap.class);
        return sysParamMap;
    }

    /**
     * 对指定Key增加值
     * @param key       缓存Key
     * @param addStep   增加数值
     */
    public void increByKey(String key, long addStep){
        stringRedisTemplate.opsForValue().increment(key , addStep);
    }

    /**
     * 对指定Key缩减值
     * @param key       缓存Key
     * @param decStep   增加数值
     */
    public void decreByKey(String key, long decStep){
        stringRedisTemplate.opsForValue().decrement(key , decStep);
    }

}
